package com.fight.strive.sys.modules.scheduler.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fight.strive.sys.modules.common.PageR;
import com.fight.strive.sys.modules.exception.StriveException;
import com.fight.strive.sys.modules.mybatis.MyBatisPlusUtils;
import com.fight.strive.sys.modules.scheduler.dao.SchExecutorMapper;
import com.fight.strive.sys.modules.scheduler.entity.SchExecutorEntity;
import com.fight.strive.sys.modules.scheduler.service.SchExecutorService;
import com.fight.strive.sys.modules.scheduler.service.SchJobService;
import com.fight.strive.sys.utils.CollectionUtils;
import com.fight.strive.sys.utils.ObjectUtils;
import com.fight.strive.sys.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
@DS("master")
public class SchExecutorServiceImpl
        extends ServiceImpl<SchExecutorMapper, SchExecutorEntity>
        implements SchExecutorService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    @Lazy
    private SchJobService schJobService;

    @Override
    public void saveE(SchExecutorEntity entity) {
        try {
            this.saveOrUpdate(entity);
            // 清空 url list 缓存
            redisTemplate.delete("t_sys_sch_executor:url_list:"
                    .concat(String.valueOf(entity.getId())));
        } catch (DuplicateKeyException e) {
            throw new StriveException("该执行器编码已存在");
        }
    }

    @Override
    public IPage<SchExecutorEntity> list(PageR<SchExecutorEntity> page) {
        QueryWrapper<SchExecutorEntity> queryWrapper = new QueryWrapper<>();
        MyBatisPlusUtils.buildAndQuery(queryWrapper, page.getCond());
        return this.page(page, queryWrapper);
    }

    @Override
    public void remove(SchExecutorEntity entity) {
        if (schJobService.executorHasJob(entity.getId())) {
            throw new StriveException("该服务下有任务，无法删除");
        }
        redisTemplate.delete(
                "t_sys_sch_executor:url_list:".concat(String.valueOf(entity.getId())));
        redisTemplate.delete(
                "t_sys_sch_executor:robin_number:".concat(String.valueOf(entity.getId())));
        this.removeById(entity.getId());
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<String> getUrls(String id) {
        List<String> urlList = (List<String>) redisTemplate.opsForValue().get(
                "t_sys_sch_executor:url_list:".concat(id));
        if (ObjectUtils.isNull(urlList)) {
            urlList = new ArrayList<>();
            SchExecutorEntity entity = this.getById(id);
            if (ObjectUtils.notNull(entity)) {
                // 以逗号分隔
                String urls = entity.getUrl();
                if (StringUtils.isNotBlank(urls)) {
                    String[] urlArr = StringUtils.split(
                            StringUtils.removeAllWhitespace(urls),
                            ",");
                    if (ObjectUtils.notNull(urlArr)) {
                        urlList = Arrays.asList(urlArr);
                    }
                }
            }
            // 更新缓存
            redisTemplate.opsForValue().set(
                    "t_sys_sch_executor:url_list:".concat(id), urlList);
        }
        return urlList;
    }

    @Override
    public String getRobinUrl(String id) {
        Long number = redisTemplate.opsForValue()
                .increment("t_sys_sch_executor:robin_number:".concat(id));
        if (ObjectUtils.notNull(number)) {
            List<String> urlList = this.getUrls(id);
            if (CollectionUtils.isNotEmpty(urlList)) {
                if (number == urlList.size()) {
                    redisTemplate.delete(
                            "t_sys_sch_executor:robin_number:".concat(id));
                }
                int index = (int) ((number - 1) % urlList.size());
                return urlList.get(index);
            }
        }
        return null;
    }
}
